﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ParserCore;
using NDimArrayNamespace;
using Memory_Access;
using QLabValues;

namespace Engine
{
    public class EngineManager
    {
        public EngineVisitor engineVisitor;
        
        public FunctionTable currentFolderFuncTable;
        public FunctionTable pathFuncTable;
        
        static private EngineManager _instance = null;
        
        public delegate void ConsoleEventHandler(string text);
        public event ConsoleEventHandler ConsoleEvent = null;

        private EngineManager()
        {
            engineVisitor = new EngineVisitor();
            pathFuncTable = new FunctionTable();
            currentFolderFuncTable = new FunctionTable();

            // add builtin functions
            pathFuncTable.AddBuiltInFunctions();
            // add builtin engine functions
            EngineFunctions engineFunctions = new EngineFunctions();
            engineFunctions.AddFunctions();
            foreach (Identifier id in EngineFunctions.FunctionsDictionary.Keys)
            {
                pathFuncTable.AddFunction(id, new BuiltInFunction(EngineFunctions.FunctionsDictionary[id]));
            }
        }
        
        static public EngineManager Instance
        {
            get
            {
                if (_instance == null)
                    _instance = new EngineManager();
                return _instance;
            }
        }

        public void Execute(string command, Dictionary<string, string> currentFolderFunctions, List<Dictionary<string, string>> PathFunctions)
        {
            // add path functions
            for (int i = 0; i < PathFunctions.Count; i++)
                pathFuncTable.AddFunctions(PathFunctions[i]);
            
            // add current folder functions (all functions in solution)
            currentFolderFuncTable = new FunctionTable();//.AddFunctions(currentFolderFunctions);
            currentFolderFuncTable.AddFunctions(currentFolderFunctions);

            // initialize and parse command
            Statement commandStatement = null;
            ParsingEngine commandParser = new ParsingEngine();
            try
            {
                commandStatement = commandParser.Parse(command, true);
            }
            catch (ParserException exception)
            {
                OnConsoleEvent("Parser error: " + exception.ParserErrorMessage);
                return;
            }
            if (commandStatement == null)
                throw new EngineException("Parse failed");

            // execute command
            commandStatement.Accept(engineVisitor);
            currentFolderFuncTable = null;
        }
                
        public void OnConsoleEvent(string text)
        {
            if(this.ConsoleEvent!= null)
                this.ConsoleEvent(text);
        }
    }
}
